<script setup lang="ts">
import { ref, watch } from "vue";
import { showToast, type UploaderFileListItem } from "vant";
import type { FileDataType } from "./types";
import http from "@/api";

const uploadFile = async (formData: FormData) => {
	return await http.upload("/mistake-api/file/upload", formData);
};
const props = defineProps<{
		modelValue: FileDataType[];
		/** 是否使用按钮类型 */
		buttonType?: boolean;
		/** 是否开启预览 */
		preview?: boolean;
		// 文件类型
		accept?: string;
		// 文件大小
		maxSize?: number;
		// 文件数量
		maxCount?: number;
	}>(),
	emits = defineEmits<{
		(e: "update:modelValue", value: FileDataType[]): void;
	}>();

const fileList = ref<UploaderFileListItem[]>([]);
const fileFormatList = ref<FileDataType[]>([]),
	uploadLoading = ref(false);

const afterRead = ({ file }: any) => {
	onUpload(file);
};

const onOversize = () => {
	showToast("文件大小不能超过 " + props.maxSize || 10 + "MB");
};

const onUpload = async (file: File) => {
	let formData = new FormData();
	const { name, type } = file || {};
	let len = name.split(/(?=[^.]+$)/)[0].length;
	if (len > 39) {
		showToast("超出文件名称最大限制");
		return false;
	}
	if (/\,|\，/.test(name)) {
		showToast("文件名称禁止包含,，");
		return false;
	}
	formData.append("parentPath", "holli-form");
	formData.append("file", file);
	let fileInfo: FileDataType = {
		fileName: "",
		fileType: "",
		fileUrl: ""
	};
	fileInfo.fileName = name;
	fileInfo.fileType = type;
	try {
		uploadLoading.value = true;
		const { data } = (await uploadFile(formData)) || {};
		fileInfo.fileUrl = data as unknown as string;
		fileFormatList.value.push(fileInfo);
		emits("update:modelValue", fileFormatList.value);
	} catch (error) {
		console.log("error", error);
	} finally {
		uploadLoading.value = false;
	}
};

const deleteFile = (option: any, { index }: { index: number }) => {
	deleteFileByIndex(index);
};

const deleteFileByIndex = (index: number) => {
	const list = [...props.modelValue];
	list.splice(index, 1);
	emits("update:modelValue", list);
};

/** 监听modalValue */
watch(
	() => props.modelValue,
	val => {
		if (val && !val.length) {
			fileList.value = [];
			fileFormatList.value = [];
		} else {
			const formatList: FileDataType[] = [],
				files: UploaderFileListItem[] = [];
			val.forEach(f => {
				formatList.push({
					fileName: f.fileName,
					fileType: f.fileType,
					fileUrl: f.fileUrl
				});
				files.push({
					url: "/mio-cdn" + f.fileUrl
				});
			});
			fileFormatList.value = formatList;
			fileList.value = files;
		}
	}
);

defineExpose({
	uploadLoading,
	deleteFileByIndex
});
</script>

<template>
	<van-uploader
		v-bind="$attrs"
		v-model="fileList"
		:preview-image="preview"
		:after-read="afterRead"
		:max-size="maxSize || 10 * 1024 * 1024"
		:accept="accept || '*'"
		:max-count="maxCount || 1"
		@delete="deleteFile"
		@oversize="onOversize"
		v-loading="uploadLoading"
	>
		<template #default v-if="props.buttonType">
			<div class="upload-button">
				<img src="@/assets/images/upload-icon.png" alt="" />
				<span>上传文件</span>
			</div>
		</template>
	</van-uploader>
	<ul v-if="buttonType && props.modelValue?.length" class="attachment-list">
		<li class="attachment" v-for="(item, index) in props.modelValue" :key="index">
			<span class="van-ellipsis">{{ item.fileName }}</span>
			<van-icon class="icon" name="cross" @click="deleteFileByIndex(index)" />
		</li>
	</ul>
</template>

<style scoped lang="less">
.upload-button {
	display: flex;
	justify-content: space-between;
	align-items: center;
	border: 1px solid #dddddd;
	padding: 5px 10px;
	&:active {
		background-color: #f5f5f5;
	}
	img {
		width: 14px;
		height: 14px;
	}
	span {
		font-size: 14px;
		color: #666666;
		margin-left: 5px;
	}
}

.attachment-list {
	margin-top: 5px;
	.attachment {
		display: flex;
		justify-content: space-between;
		align-items: center;
		border: 1px solid #bbd1d4;
		padding: 2px 5px;
		span {
			border: none !important;
			padding: 0;
			width: 90%;
			white-space: nowrap;
			overflow-x: auto;
			// 隐藏滚动条
			&::-webkit-scrollbar {
				display: none;
			}
		}
		.icon {
			margin-left: 5px;
			font-size: 14px;
		}
	}
}
</style>
